#pragma once

#include "map/griddefines.h"
#include "object/objectguid.h"

enum InstanceConditionIDs                                   // Suggested values used with CONDITION_INSTANCE_SCRIPT for some generic uses
{
    // for hard-mode loot (0 normal; 1,2... hard,harder... mode)
    INSTANCE_CONDITION_ID_NORMAL_MODE = 0,
    INSTANCE_CONDITION_ID_HARD_MODE = 1,
    INSTANCE_CONDITION_ID_HARD_MODE_2 = 2,
    INSTANCE_CONDITION_ID_HARD_MODE_3 = 3,
    INSTANCE_CONDITION_ID_HARD_MODE_4 = 4,

    // to check for which team the instance is doing scripts
    INSTANCE_CONDITION_ID_TEAM_HORDE = 67,
    INSTANCE_CONDITION_ID_TEAM_ALLIANCE = 469,
};

enum LootType
{
    LOOT_CORPSE = 1,
    LOOT_PICKPOCKETING = 2,
    LOOT_FISHING = 3,
    LOOT_DISENCHANTING = 4,
    // ignored always by client
    LOOT_SKINNING = 6,                        // unsupported by client, sending LOOT_PICKPOCKETING instead

    LOOT_FISHINGHOLE = 20,                       // unsupported by client, sending LOOT_FISHING instead
    LOOT_FISHING_FAIL = 21,                       // unsupported by client, sending LOOT_FISHING instead
    LOOT_INSIGNIA = 22                        // unsupported by client, sending LOOT_CORPSE instead
};

class Map;
class InstanceData
{
public:

    explicit InstanceData(Map* map) : instance(map) {}
    virtual ~InstanceData() {}

    Map* instance;

    // On creation, NOT load.
    virtual void Initialize() {}

    // On load
    virtual void Load(const char* /*data*/) {}

    // When save is needed, this function generates the data
    virtual const char* Save() const { return ""; }

    void SaveToDB() const;

    // Called every map update
    virtual void Update(unsigned int /*diff*/) {}

    // This is to prevent players from entering during boss encounters.
    virtual bool IsEncounterInProgress() const { return false; };

    // Called when a player successfully enters the instance (after really added to map)
    virtual void OnPlayerEnter(battle::object::Player*) {}

    // Called when a player dies inside instance
    virtual void OnPlayerDeath(battle::object::Player*) {}

    // Called when a player leaves the instance (before really removed from map (or possibly world))
    virtual void OnPlayerLeave(battle::object::Player*) {}

    // Called when a gameobject is created
    virtual void OnObjectCreate(battle::object::GameObject*) {}

    // called on creature creation
    virtual void OnCreatureCreate(battle::object::Creature* /*creature*/) {}

    // called on creature enter combat
    virtual void OnCreatureEnterCombat(battle::object::Creature* /*creature*/) {}

    // called on creature evade
    virtual void OnCreatureEvade(battle::object::Creature* /*creature*/) {}

    // called on creature death
    virtual void OnCreatureDeath(battle::object::Creature* /*creature*/) {}

    // called on creature despawn
    virtual void OnCreatureDespawn(battle::object::Creature* /*creature*/) {}

    // called on game event
    virtual void OnEventHappened(unsigned short /*event_id*/, bool /*activate*/, bool /*resume*/) {}

    // called on creature looted
    virtual void OnCreatureLooted(battle::object::Creature* /*creature*/, LootType) {}

    // All-purpose data storage 64 bit
    virtual unsigned long long GetData64(unsigned int /*Data*/) const { return 0; }
    virtual void SetData64(unsigned int /*Data*/, unsigned long long /*Value*/) {}

    // Guid data storage (wrapper for set/get from unsigned long long storage
    ObjectGuid GetGuid(unsigned int dataIdx) const { return ObjectGuid(GetData64(dataIdx)); }
    void SetGuid(unsigned int dataIdx, ObjectGuid value) { SetData64(dataIdx, value.GetRawValue()); }

    // All-purpose data storage 32 bit
    virtual unsigned int GetData(unsigned int /*Type*/) const { return 0; }
    virtual void SetData(unsigned int /*Type*/, unsigned int /*Data*/) {}

    // Condition criteria additional requirements check
    // This is used for such things are heroic loot
    // See ObjectMgr.h enum ConditionSource for possible values of conditionSourceType
    virtual bool CheckConditionCriteriaMeet(battle::object::Player const* source, unsigned int instance_condition_id, battle::object::WorldObject const* conditionSource, unsigned int conditionSourceType) const;
};
